package com.shxy.api.service.impl;

import com.shxy.api.bean.news.CatalogBean;
import com.shxy.api.bean.news.NewsBean;
import com.shxy.api.bean.news.NewsInfo;
import com.shxy.api.bean.user.UserInfo;
import com.shxy.api.dao.news.CatalogDao;
import com.shxy.api.dao.news.NewsDao;
import com.shxy.api.dao.news.NewsInfoDao;
import com.shxy.api.dao.user.UserDao;
import com.shxy.api.service.INewsService;
import org.apache.commons.text.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 新闻管理实现类
 */
@Service
public class NewsSerivce implements INewsService {
    @Autowired private CatalogDao catalogDao;
    @Autowired private NewsDao newsDao;
    @Autowired private NewsInfoDao newsInfoDao;
    @Autowired private UserDao userDao;

    @Override
    public boolean isCatalogExist(String name, String parentId) {
        // 1、获取父节点
        Optional<CatalogBean> op= catalogDao.findById(parentId);
        return catalogDao.existsByNameAndParent(name, op.isEmpty() ? null : op.get());
    }

    @Override
    public CatalogBean addCatalog(String name, String parentId) {
        Optional<CatalogBean> op= catalogDao.findById(parentId);
        CatalogBean cb = op.isEmpty() ? null : op.get();
        CatalogBean c = new CatalogBean();
        c.setName(name);
        c.setParent(cb);
        return catalogDao.save(c);
    }

    @Override
    public boolean isCatalogExist(String id) {
        return !catalogDao.findById(id).isEmpty();
    }

    @Override
    public CatalogBean getCatalogById(String id) {
        Optional<CatalogBean> op = catalogDao.findById(id);
        if(op.isPresent()) {
            return op.get();
        }
        return null;
    }

    @Override
    public List<CatalogBean> getChildrenCatalogs(String catalogId) {
        return catalogDao.findAllByParentId(catalogId);
    }

    @Override
    public boolean modifyCatalogName(String id, String name) {
        CatalogBean catalog = catalogDao.findById(id).get();
        catalog.setName(name);
        catalogDao.save(catalog);
        return true;
    }

    @Override
    public boolean moveCatalog(String id, String parentId) {
        // 1、获取子节点
        CatalogBean catalog = catalogDao.findById(id).get();
        // 2、获取父节点
        CatalogBean parent = !parentId.equals("") ? catalogDao.findById(parentId).get() : null;
        // 3、设置子节点的父节点
        catalog.setParent(parent);
        // 4、保存
        catalogDao.save(catalog);
        return true;
    }

    @Override
    public boolean deleteCatalogById(String id) {
        // 1、给栏目下的新闻打上未分类标记
        List<NewsInfo> newsList = newsInfoDao.findAllByCatalogId(id);
        newsList.stream().forEach(newsInfo -> {
            NewsBean news = newsInfo.getNews();
            news.setCataloged(false);
            newsDao.save(news);
        });
        // 2、删除该栏目下的所有新闻
        newsInfoDao.deleteAllByCatalogId(id);
        // 3、删除栏目
        if(catalogDao.existsById(id)) {
            catalogDao.deleteById(id);
            return true;
        }
        return false;
    }

    @Override
    public int deleteCatalogAll() {
        List<CatalogBean> catalogs = catalogDao.findAll();
        catalogDao.deleteAll(catalogs);
        return catalogs.size();
    }

    @Override
    public boolean isNewsExists(String title, String catalogId) {
        return newsInfoDao.findByCatalogIdAndNewsTitle(catalogId, title) != null;
    }

    @Override
    public NewsInfo saveNews(String title, String content, String catalogId, String authorId) {
        // 1、获取作者信息
        UserInfo author = userDao.findById(authorId).get();
        // 2、保存新闻内容
        NewsBean news = new NewsBean();
        news.setTitle(title);
        news.setContent(StringEscapeUtils.escapeHtml4(content));
        news.setAuthor(author);
        news.setUpdateTime(new Date().getTime());
        news = newsDao.save(news);

        // 3、获取栏目
        CatalogBean catalog = catalogDao.findById(catalogId).get();
        // 4、保存新闻信息
        NewsInfo ni = new NewsInfo();
        ni.setNews(news);
        ni.setCatalog(catalog);

        return newsInfoDao.save(ni);
    }

    @Override
    public boolean updateNews(NewsBean news) {
        return false;
    }

    @Override
    public NewsInfo getNewsInfoById(String id) {
        Optional<NewsInfo> op = newsInfoDao.findById(id);
        if(op.isPresent()) {
            return op.get();
        }
        return null;
    }

    @Override
    public List<CatalogBean> getCatalogsAll() {
        List<CatalogBean> catalogs = catalogDao.findAllByParent(null);
        catalogs.stream().forEach(catalogBean -> {
            catalogBean.setChildrenList(getSubCatalogs(catalogBean));
        });
        return catalogs;
    }

    @Override
    public Page<NewsInfo> getPagedNewsOfCatalog(String catalogId, int page, int size) {
        // 1、构建分页
        Pageable pageable = PageRequest.of(page-1, size);
        return newsInfoDao.findAllByCatalogId(catalogId, pageable);
    }

    @Override
    public Page<NewsInfo> getPagedNewsOfCatalog(String catalogId, int page, int size, boolean isAll) {
        // 1、构建分页
        PageRequest pageable = PageRequest.of(page - 1, size);
        // 2、构建节点列表
        List<CatalogBean> catalogs = new ArrayList<>(); // 节点列表
        catalogs.add(catalogDao.findById(catalogId).get()); // 添加选中节点
        List<CatalogBean> list = catalogDao.findAllByParentId(catalogId);   // 添加子节点
        catalogs.addAll(list);
        // 3、分页查询
        return newsInfoDao.findAllByCatalogIn(catalogs, pageable);
    }

    /**
     * 递归获取子节点
     * @param catalog
     * @return
     */
    private List<CatalogBean> getSubCatalogs(CatalogBean catalog) {
        // 1、查询该节点的子节点列表
        List<CatalogBean> nodes = catalogDao.findAllByParent(catalog);

        // 2、如果存在子节点，则循环查询子节点的子节点
        nodes.stream().forEach(catalogBean -> {
            catalogBean.setChildrenList(getSubCatalogs(catalogBean));
        });

        // 3、将子节点赋值给该节点
        catalog.setChildrenList(nodes);

        // 4、返回该节点
        return nodes;
    }
}
